import json

from selenium import webdriver
from selenium.common import TimeoutException
from selenium.webdriver.chrome.service import Service  # 新增
from selenium.webdriver.chrome.options import Options
import time
import os,sys
import config_manager
from startup_optimizer import startup_optimizer # 新增导入

class BastionPageLoader:
    def __init__(self):
        self.driver = None
        self.active_sessions = {}  # 存储活动会话 {ip: window_handle}

        # 配置加载
        config = config_manager.ConfigManager()
        if config.get_driver_path():
            self.driver_path = config.get_driver_path()
        else:
            self.driver_path = os.path.join(os.path.dirname(sys.executable), "chromedriver.exe")

        if config.get_chrome_path():
            self.chrome_binary_path = config.get_chrome_path()
        else:
            self.chrome_binary_path = r"C:\Program Files\Google\Chrome\Application\chrome.exe"




        # 新增会话保存路径
        # self.session_dir = os.path.join(os.path.dirname(sys.executable), "sessions")
        # os.makedirs(self.session_dir, exist_ok=True)


    def initialize_driver(self):
        """初始化Chrome驱动"""
        try:
            # 如果驱动已存在且有效，直接返回
            if self.driver is not None:
                if self.is_browser_alive():
                    return True
                else:
                    # 如果驱动不活跃，尝试关闭它并设置为None
                    try:
                        self.driver.quit()
                        print("旧的Chrome驱动已关闭。")
                    except Exception as quit_e:
                        print(f"关闭旧Chrome驱动时发生错误: {quit_e}")
                    finally:
                        self.driver = None  # 确保driver引用被清除

            chrome_options = Options()
            chrome_options.add_experimental_option("detach", True)  # 防止自动关闭

            # 验证并设置路径
            if not os.path.exists(self.chrome_binary_path):
                print(f"错误: Chrome浏览器路径不存在: {self.chrome_binary_path}")
                return False
            chrome_options.binary_location = self.chrome_binary_path

            if not os.path.exists(self.driver_path):
                print(f"错误: ChromeDriver路径不存在: {self.driver_path}")
                return False

            # 设置Chrome选项
            # chrome_options.add_argument("--new-window")  # 允许新窗口
            chrome_options.add_argument("--new-tab")  # 允许新标签页
            chrome_options.add_argument("--disable-features=OpenWindowFromTab")
            chrome_options.add_argument("--start-maximized")
            chrome_options.add_argument('--ignore-certificate-errors') # 忽略证书错误
            chrome_options.add_argument('--allow-running-insecure-content') # 允许不安全内容
            chrome_options.add_argument('--allow-insecure-content')
            chrome_options.add_argument('--ssl-version-min=tls1')  # 设置最低TLS版本
            # chrome_options.add_argument('--ssl-version-min=tls1.2')
            chrome_options.add_argument('--cipher-suite-blacklist=0x0004,0x0005,0xC011,0xC007,0x000A,0x0016') # 禁用不安全的加密套件
            chrome_options.add_argument('--cipher-suite-blacklist=0x000A,0x0016')  # 禁用更多不安全套件
            chrome_options.add_argument('--disable-extensions')  # 禁用所有浏览器扩展
            chrome_options.add_argument('--disable-component-extensions-with-background-pages')  # 禁用带有后台页面的组件扩展
            chrome_options.add_argument('--disable-background-networking')  # 禁用后台网络活动
            chrome_options.add_argument('--disable-infobars')  # 禁用信息栏(如"Chrome正受到自动测试软件控制"的提示)
            # 在Chrome选项中添加连接管理参数
            chrome_options.add_argument('--disable-http2')  # 禁用HTTP/2
            chrome_options.add_argument('--disable-quic')  # 禁用QUIC
            # 将 startup_optimizer 中的 Selenium 优化选项添加到 chrome_options
            # 假设 optimize_selenium_startup 现在返回 (常规参数列表, 实验性排除开关列表)
            regular_args, experimental_exclude_switches = startup_optimizer.optimize_selenium_startup()
            # 确保 excludeSwitches 选项只添加一次
            chrome_options.add_experimental_option("excludeSwitches", experimental_exclude_switches)
            for arg in regular_args:
                # 避免添加 --headless=new 参数，因为它会导致浏览器不显示窗口
                if arg == '--headless=new':
                    continue
                chrome_options.add_argument(arg)
            chrome_options.add_argument('--disable-site-isolation-trials')  # 禁用站点隔离试验功能
            chrome_options.add_argument('--disable-features=IsolateOrigins,site-per-process')  # 禁用站点隔离和进程隔离功能
            chrome_options.add_argument('--allow-insecure-localhost')  # 允许本地主机的非安全连接
            chrome_options.add_argument('--reduce-security-for-testing')  # 降低安全级别以便测试
            chrome_options.add_argument('--no-sandbox')  # 禁用沙盒模式(提高兼容性但降低安全性)
            chrome_options.add_argument("--enable-features=NetworkServiceInProcess")

            # 初始化Chrome驱动
            service = Service(executable_path=self.driver_path)
            self.driver = webdriver.Chrome(service=service, options=chrome_options)

            # 注册标签页关闭事件监听器
            # self.register_tab_closed_listener()

            return True
        except Exception as e:
            print(f"初始化Chrome驱动失败: {e}")
            return False

    def register_tab_closed_listener(self):
        """注册标签页关闭事件监听器"""
        if not self.driver:
            return

        # 设置轮询检查标签页状态的脚本
        self.driver.execute_script("""
            // 创建一个全局变量存储上次的标签页数量
            window.lastTabCount = window.open('', '_self').length;

            // 定期检查标签页数量变化
            setInterval(function() {
                var currentTabCount = window.open('', '_self').length;
                if (currentTabCount < window.lastTabCount) {
                    // 标签页数量减少，发送关闭事件
                    console.log('Tab closed');
                    // 这里可以通过自定义事件或存储在localStorage中通知
                    localStorage.setItem('tabClosed', Date.now());
                }
                window.lastTabCount = currentTabCount;
            }, 1000);
        """)

    def open_bastion_page(self, url, title):
        """打开堡垒机页面，优先使用缓存的会话"""
        try:
            # 确保驱动已初始化
            if not self.initialize_driver():
                return False

            # 从URL中提取IP地址
            ip = url.replace("https://", "").replace("http://", "").split("/")[0]

            # 检查是否已有该IP的会话
            if ip in self.active_sessions:
                handle = self.active_sessions[ip]
                if handle in self.driver.window_handles:
                    # 切换到已有标签页
                    self.driver.switch_to.window(handle)
                    self.driver.execute_script(f"document.title='{title}'")
                    return True
                else:
                    # 句柄已失效，从映射中移除
                    del self.active_sessions[ip]

            print("打开页面前窗口句柄:", self.driver.window_handles)
            
            # 检查当前窗口数量
            if len(self.driver.window_handles) == 1 and  self.driver.current_url == "data:,":
                # 如果只有一个窗口（首次打开浏览器时的空白页），直接在当前页面加载URL
                self.driver.get(url)
            else:
                # 如果已经有多个窗口，创建新标签页
                self.driver.switch_to.new_window('tab')
                self.driver.get(url)
                
            print("加载URL后窗口句柄:", self.driver.window_handles)
            self.driver.execute_script(f"document.title='{title}'")
    
            # 确保切换到当前标签页并记录映射
            # print(f"打开堡垒机页面失败: {e}")
            current_handle = self.driver.window_handles[-1]
            self.driver.switch_to.window(current_handle)
            self.active_sessions[ip] = current_handle  # 记录IP与句柄的映射
            self.driver.switch_to.window(self.driver.window_handles[-1])
            return True
        except Exception as e:
            print(f"打开堡垒机页面失败: {e}")  # 取消注释以便调试
            return False

    def is_browser_alive(self):
        """安全地检查浏览器是否还在运行"""
        try:
            self.driver.execute_script("return navigator.userAgent")
            return True
        except:
            return False

